<script lang="ts">
    import { onMount } from 'svelte'
    import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
    import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls'
    import { MeshPhongMaterial, Mesh, Sphere, Group, Scene, Box3,
        SpotLight, AmbientLight, BoxGeometry, Vector3,
        Color } from 'three'

    import { createRenderer } from './utils/renderer'
    import { createPerspectiveCamera } from './utils/camera'

    import { CSG } from 'three-csg-ts'

    const stlLoader = new STLLoader()
    const url = '/models/stl2.stl'
    /* const url = '/models/fei.stl' */
    /* const url = '/models/涡轮发动机/涡轮发动机/part_11.stl' */
    const mat = new MeshPhongMaterial({ color: new Color(0.901961, 0.913725, 0.92549) })

    let width = 800
    let height = 600
    let aspect = width / height
    let canvas
    let bbox = new Box3()
    let group = new Group()
    let bsphere = new Sphere()
    let controls
    let mesh

    const camera = createPerspectiveCamera({ fov: 20, aspect, near: 1, far: 10000, zoom: 1 })
    let renderer
    const scene = new Scene()
    scene.add(group)
    const ambientLight = new AmbientLight( 0x888888, 0.6 )
    const spotLight = new SpotLight(0xffffff)

    function updateBBox () {
        bbox.makeEmpty()
        bbox.expandByObject( group )
        console.log(bbox)
        bbox.getBoundingSphere( bsphere )
    }

    function clip () {
        console.log('start clipping...')
        let s = +new Date
        const size = new Vector3()
        bbox.getSize(size)
        const geo = new BoxGeometry(size.x, size.y, size.z)
        const boundingBoxMesh = new Mesh(geo, new MeshPhongMaterial({
            color: 0x0fff0f,
            opacity: 0.3,
            transparent: true,
        }))
        let position = bsphere.center.clone()
        position.z += size.z / 2
        boundingBoxMesh.position.copy(position)
        boundingBoxMesh.updateMatrix()
        const submesh = CSG.subtract(mesh, boundingBoxMesh)
        let e = +new Date
        console.log((e - s)/1000)
        console.log(submesh)
        group.remove(mesh)
        group.add(submesh)
        group.add(boundingBoxMesh)
        updateBBox()
        updateCamera()
    }

    function updateCamera () {
        const { radius, center } = bsphere

        camera.position.copy( center.clone().addScalar( radius * 3.4 ) )
        camera.near = radius / 1000
        camera.far = radius * 50
        camera.up.set( 0, 1, 0 )
        camera.lookAt(center)
        camera.updateProjectionMatrix()
    }

    function initLights () {
        spotLight.position.set( 0, 1000, 0 )
        spotLight.angle = Math.PI * 2 / 3
        spotLight.intensity = 0.4

        scene.add(ambientLight)
        scene.add(spotLight)
    }

    function updateLights () {
        const { radius, center } = bsphere
        const dir = camera.position.clone().sub( center ).normalize()
        spotLight.position.copy( center.clone().addScaledVector( dir, radius * 100 ) )
    }

    function animate () {
        renderer.render(scene, camera)
        controls.update()
        requestAnimationFrame(() => {
            animate()
        })
    }

    onMount(() => {
        controls = new TrackballControls(camera, canvas)
        initLights()
        renderer = createRenderer({ canvas, width: 800, height: 600 })
        animate()
        stlLoader.load(url, (geo) => {
            mesh = new Mesh(geo, mat)
            group.add(mesh)
            updateBBox()
            controls.target.copy(bsphere.center)
            updateCamera()
            updateLights()
            clip()
        })
    })

</script>

<main>
    <h1>stl csg</h1>
    <canvas id="hello" bind:this={canvas}></canvas>
</main>

<style>
    #hello {
        width: 800px;
        height: 600px;
        border: 1px solid orange;
        background: #000ff0;
    }
</style>
